package io.kiki.sba.registry.server.clientInterface.providedata;

import io.kiki.sba.registry.common.model.console.PersistenceData;
import io.kiki.sba.registry.common.model.constants.ValueConstants;
import io.kiki.sba.registry.common.model.metaserver.ShutdownSwitch;
import io.kiki.sba.registry.server.clientInterface.bootstrap.Bootstrap;
import io.kiki.sba.registry.server.clientInterface.bootstrap.Config;
import io.kiki.sba.registry.server.clientInterface.providedata.FetchShutdownService.ShutdownStorage;
import io.kiki.sba.registry.server.shared.providedata.AbstractFetchPersistenceSystemProperty;
import io.kiki.sba.registry.server.shared.providedata.SystemDataStorage;
import io.kiki.sba.registry.store.api.meta.ProvideDataRepository;
import io.kiki.sba.registry.util.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;


public class FetchShutdownService extends AbstractFetchPersistenceSystemProperty<ShutdownStorage, ShutdownStorage> {

    private static final Logger logger = LoggerFactory.getLogger(FetchShutdownService.class);
    private static final ShutdownStorage INIT = new ShutdownStorage(INIT_VERSION, ShutdownSwitch.defaultSwitch());
    @Autowired
    private Config config;
    @Resource
    private FetchStopPushService fetchStopPushService;
    @Autowired
    private Bootstrap bootstrap;
    @Autowired
    private ProvideDataRepository provideDataRepository;

    public FetchShutdownService() {
        super(ValueConstants.SHUTDOWN_SWITCH_DATA_ID, INIT);
    }

    @Override
    protected int getSystemPropertyIntervalMillis() {
        return config.getSystemPropertyIntervalMillis();
    }

    @Override
    protected ShutdownStorage fetchFromPersistence() {
        PersistenceData persistenceData = provideDataRepository.get(ValueConstants.SHUTDOWN_SWITCH_DATA_ID);
        if (persistenceData == null) {
            return INIT;
        }
        ShutdownSwitch shutdownSwitch = JsonUtils.read(persistenceData.getData(), ShutdownSwitch.class);
        ShutdownStorage update = new ShutdownStorage(persistenceData.getVersion(), shutdownSwitch);
        return update;
    }

    @Override
    protected boolean doProcess(ShutdownStorage expect, ShutdownStorage update) {
        try {
            if (running2stop(expect.shutdownSwitch, update.shutdownSwitch)) {
                if (!fetchStopPushService.isStopPushSwitch()) {
                    logger.error("forbid stop server when pushSwitch is open.");
                    return false;
                }
                logger.info("stop server when pushSwitch is close, prev={}, current={}", expect.shutdownSwitch, update.shutdownSwitch);
                bootstrap.destroy();
            }
            return true;
        } catch (Throwable e) {
            logger.error("Fetch stop server switch error", e);
        }
        return false;
    }

    private boolean running2stop(ShutdownSwitch current, ShutdownSwitch update) {
        return !current.isShutdown() && update.isShutdown();
    }

    public boolean isShutdown() {
        return storage.get().shutdownSwitch.isShutdown();
    }


    public FetchShutdownService setSessionServerConfig(Config config) {
        this.config = config;
        return this;
    }


    public FetchShutdownService setSessionServerBootstrap(Bootstrap bootstrap) {
        this.bootstrap = bootstrap;
        return this;
    }


    public FetchShutdownService setFetchStopPushService(FetchStopPushService fetchStopPushService) {
        this.fetchStopPushService = fetchStopPushService;
        return this;
    }

    protected static class ShutdownStorage extends SystemDataStorage {

        private ShutdownSwitch shutdownSwitch;

        public ShutdownStorage(long version, ShutdownSwitch shutdownSwitch) {
            super(version);
            this.shutdownSwitch = shutdownSwitch;
        }
    }
}
